package cn.remex.db.utils;

import cn.remex.RemexConstants;
import cn.remex.core.exception.StringHandleException;
import cn.remex.db.utils.exception.ServiceCode;
import org.apache.oro.text.regex.*;

import java.io.*;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.function.BiConsumer;

/**
 * String 处理工具类
 */
public class StringHelper implements RemexConstants {
	private static HashMap<String, Pattern> patterns = new HashMap<String, Pattern>();

	private static HashMap<Class<?>, String> ClassAbbreviation = new HashMap<Class<?>, String>();
	/**
	 * 取类名的所有大写字母
	 *
	 * @param type 类名
	 * @return String 返回的字符串
	 */
	public static String getAbbreviation(final Type type) {
		if (type instanceof Class<?>) {
			String abbr = ClassAbbreviation.get(type);
			if (null == abbr) {
				String sn = getClassSimpleName(type);
				abbr = sn.replaceAll("[^A-Z]", "");
				ClassAbbreviation.put((Class<?>) type, abbr);
			}
			return abbr;
		} else {
			throw new StringHandleException(ServiceCode.FAIL, "因为此Type非Class类型，无法为Type" + type.toString() + "类指定缩写！");
			// return null;//never arrived here
		}

	}

	/**
	 * 为类简名
	 *
	 * @param type 类名
	 * @return String 返回的类简名
	 */

	public static String getClassSimpleName(final Type type) {
		if (type instanceof Class<?>) {
			String sn = ((Class<?>) type).getSimpleName();
			return sn.split("\\$\\$EnhancerByCGLIB\\$\\$")[0];
		} else {
			throw new StringHandleException(ServiceCode.FAIL, "因为此Type非Class类型，无法为Type" + type.toString() + "类简名！");
			// return null;//never arrived here
		}

	}

	/**
	 * 获取类名
	 *
	 * @param type 类名
	 * @return String 字符串
	 */
	public static String getClassName(final Type type) {
		if (type instanceof Class<?>) {
			String sn = ((Class<?>) type).getName();
			return sn.split("\\$\\$EnhancerByCGLIB\\$\\$")[0];
		} else {
			throw new StringHandleException(ServiceCode.FAIL, "因为此Type非Class类型，无法为Type" + type.toString() + "类简名！");
			// return null;//never arrived here
		}

	}

	/**
	 * 字符串第一个字母转为小写
	 *
	 * @param string 字符串
	 * @return String 转化结果
	 */
	public static String lowerFirstLetter(final String string) {
		StringBuilder sb = new StringBuilder();
		return sb.append(string.substring(0, 1).toLowerCase()).append(string.substring(1)).toString();
	}

	/**
	 * 验证字符串是否匹配正则表达式
	 *
	 * @param string               被测试的字符串
	 * @param regex                匹配的正则表达式
	 * @param notMatchExceptionMsg 没有匹配时报异常的信息
	 * @return　MatchResult 匹配操作的结果
	 */
	public static MatchResult match(final String string, final String regex, final String notMatchExceptionMsg) {
		PatternMatcher m = new Perl5Matcher();
		Pattern p = obtainPattern(regex);
		if (!m.contains(string, p) && null != notMatchExceptionMsg) {
			throw new StringHandleException(ServiceCode.FAIL, notMatchExceptionMsg);
		}
		return m.getMatch();
	}

	private static synchronized Pattern obtainPattern(String regex) {
		Pattern p = patterns.get(regex);
		if (null == p) {
			try {
				p = compiler.compile(regex);
				patterns.put(regex, p);
			} catch (MalformedPatternException e) {
				throw new StringHandleException(ServiceCode.FAIL, "连接正则表达式发生异常！", e);
			}
		}
		return p;
	}

	public static int forEachMatch(final String string, final String regex, BiConsumer<MatchResult, Boolean> matchConsumer) {
		PatternMatcher m = new Perl5Matcher();
		Pattern p = obtainPattern(regex);
		PatternMatcherInput input = new PatternMatcherInput(string);
		int len = string.length();
		while (m.contains(input, p)) {
			matchConsumer.accept(m.getMatch(), input.endOfInput());
		}

		return input.getEndOffset();
	}




	/**
	 * 将字符串首字母转为大写
	 *
	 * @param string 要处理的字符串
	 * @return String 处理后的字符串
	 */
	public static String upperFirstLetter(final String string) {
		return string.substring(0, 1).toUpperCase() + string.substring(1);
	}

	public static String exCharset(String str, String fromCharset, String toCharset) {
		try {
			return new String(str.getBytes(fromCharset), toCharset);
		} catch (UnsupportedEncodingException e) {
			throw new StringHandleException(ServiceCode.FAIL, "转换String时字符集不受支持", e);
		}
	}


	public static String urlDecode(String data, String charset) {
		try {
			data = data.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
			data = data.replaceAll("\\+", "%2B");
			data = URLDecoder.decode(data, charset);
			return data;
		} catch (UnsupportedEncodingException e) {
			throw new StringHandleException(ServiceCode.FAIL, "URLDecode时，转换String时字符集不受支持", e);
		}
	}

}
